/*
 * Пакет "Экосистема"
 * реализует модель экологической системы
 */
package vitarium.ecosystem;

import vitarium.ecosystem.flora.*;
import vitarium.ecosystem.fauna.*;

import java.util.Iterator;
import java.util.LinkedList;

/** Класс Экосистема */
public class EcoSystem {

    private int livedTime; // время от создания
    private int sunEnergyPerTurn; // количество солнечной энергии за единицу времени
    private int sizeFromWestToEast; // Количество клеток с Запада на Восток
    private int sizeFromNorthToSouth; // Количество клеток с Севера на Юг
    private Edaphotope ecoMap[][]; // Массив карты
    // Коллекции объектов
    private LinkedList producensList; // Список продуцентов - растений
    private LinkedList primaryConsumensList; // Список консументов 1 порядка - травоядных
    private LinkedList secondaryConsumensList; // Список консументов 2 порядка - плотоядных
    private LinkedList reducensList; // Список редуцентов - бактерий и грибов
    /** Массивы характеристик карты
    Первоначальные характеристики локаций
     * 1 - суша
     * 0 - вода
     */
    public int mapOriginalEdaphotope[][] = {
        {0, 1, 1, 1, 1, 1},
        {1, 1, 1, 1, 1, 1},
        {1, 1, 1, 1, 1, 1},
        {1, 1, 1, 0, 1, 1},
        {1, 1, 1, 1, 0, 1},
        {1, 1, 1, 1, 1, 1}
    };
    /** Первоначальные характеристики расположения живых существ
     * 0 - ничего
     * 
     * 1 - продуцент
     * 2 - консумент 1 порядка
     * 3 - консумент 2 порядка
     * 4 - редуцент
     */
    public int mapOriginalBiocoenosis[][] = {
        {0, 0, 1, 0, 2, 1},
        {0, 2, 3, 0, 1, 1},
        {1, 0, 1, 0, 1, 0},
        {0, 3, 0, 0, 0, 2},
        {1, 0, 0, 0, 1, 0},
        {1, 0, 2, 0, 2, 0},};

    /* Конструктор */
    public EcoSystem() {
        sizeFromWestToEast = 6;
        sizeFromNorthToSouth = 6;

        producensList = new LinkedList();
        primaryConsumensList = new LinkedList();
        secondaryConsumensList = new LinkedList();
        reducensList = new LinkedList();

        /* Создаем мир */
        generateWorld();
    }

    /* Функции экосистемы */
    /** Генерация карты */
    private void generateWorld() {
        livedTime = 0; // время жизни - 0 - "Рождение мира"

        ecoMap = new Edaphotope[sizeFromNorthToSouth][sizeFromWestToEast]; // задание типов ландшафтов для клеток

        for (int i = 0; i < sizeFromNorthToSouth; i++) {
            for (int j = 0; j < sizeFromWestToEast; j++) {
                switch (mapOriginalEdaphotope[i][j]) {
                    case 0:
                        ecoMap[i][j] = new WaterBasin(this, i, j);
                        break;
                    case 1:
                        ecoMap[i][j] = new Soil(this, i, j);
                        break;
                    default:
                        ecoMap[i][j] = new Soil(this, i, j);
                }
            }
        }

        for (int i = 0; i < sizeFromNorthToSouth; i++) {
            for (int j = 0; j < sizeFromWestToEast; j++) {
                // Если клетка с данными координами подходит для размещения объектов
                if (WaterBasin.class != this.getEdaphotope(j, i).getClass()) {

                    switch (mapOriginalBiocoenosis[i][j]) {
                        case 0: // Пустая клетка
                            break;
                        case 1: // "Сажаем" растение
                            producensList.add(new Beech(this, j, i));
                            //     System.out.println( getElement(i,j,producensList).longitude + " " + getElement(i,j,producensList).latitude );
                            break;
                        case 2: // Травоядное
                            primaryConsumensList.add(new Caribou(this, j, i));
                            break;
                        case 3:  // Хищник
                            secondaryConsumensList.add(new Bear(this, j, i));
                            break;
                        case 4: // Бактерии
                            producensList.add(new Reducens(this, j, i));
                            break;
                        default:
                            break;
                    }
                }
            }
        }
    }

    /** Возвращает время жизни экосистемы*/
    public int getLivedTime() {
        return livedTime;
    }

    /** Новый ход */
    public void nextTurn() {
        livedTime++;

        Producens producens;
        PrimaryConsumens primConsumens;
        SecondaryConsumens secConsumens;
        Iterator it;
        it = this.primaryConsumensList.iterator();
        while (it.hasNext()) {
            primConsumens = (PrimaryConsumens) it.next();
            primConsumens.live();
        }

        it = this.secondaryConsumensList.iterator();
        while (it.hasNext()) {
            secConsumens = (SecondaryConsumens) it.next();
            secConsumens.live();
        }
    }

    /* Функции отображения */
    /** Возвращает количество клеток с Севера на Юг */
    public int getSizeFromNorthToSouth() {
        return sizeFromNorthToSouth;
    }

    /** Возвращает количество клеток с Запада на Восток */
    public int getSizeFromWestToEast() {
        return sizeFromWestToEast;
    }

    /** Возвращает список растений */
    public LinkedList getProducensList() {
        return producensList;
    }

    /** Возвращает список травоядных */
    public LinkedList getPrimaryConsumensList() {
        return primaryConsumensList;
    }

    /** Возвращает список хищников */
    public LinkedList getSecondaryConsumensList() {
        return secondaryConsumensList;
    }

    /** Возвращает список сапрофагов */
    public LinkedList getReducensList() {
        return reducensList;
    }

    /** Возвращает эдафотоп c координатами i и j*/
    public Edaphotope getEdaphotope(int i, int j) {
        return ecoMap[j][i];
    }

    /** Возвращает элемент с координатами x и y из list */
    public BiocoenosisElement getElementFromList(int x, int y, LinkedList list) {

        Iterator it = list.iterator();
        /** По умолчанию элемент пустой*/
        BiocoenosisElement foundElement = null;
        while (it.hasNext()) {
            BiocoenosisElement element = (BiocoenosisElement) it.next();
            if (element.getLongitude() == x & element.getLatitude() == y) {
                foundElement = element;
            }
        }
        return foundElement;
    }

    /** Перегруженный метод */
    public BiocoenosisElement getElement(int x, int y) {

        BiocoenosisElement foundBiocoenosisElement; // Найденный объект
        foundBiocoenosisElement = getElementFromList(x, y, producensList);
        // Не продуцент
        if (foundBiocoenosisElement == null) {
            foundBiocoenosisElement = getElementFromList(x, y, primaryConsumensList);
            // Не консумент первого порядка
        }
        if (foundBiocoenosisElement == null) {
            foundBiocoenosisElement = getElementFromList(x, y, secondaryConsumensList);
            // Не консумент второго порядка
        }
        return foundBiocoenosisElement;
    }
}

/** Вспомогательный класс для передачи координат локации */
class Location {

    Location(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public int x; // longitude
    public int y; // latitude
}
